
#include "REPL.h"

/*
 * just initialised a new buffer
 * return the structure of buffer for containing the next input token
 */
InputBuffer *new_input_buffer() {//
    InputBuffer *input_buffer = malloc(sizeof(InputBuffer));//dynamic memory in the heap
    input_buffer->buffer = NULL;//the token chars haven't pointed to anything
    input_buffer->buffer_length = 0;
    input_buffer->input_length = 0;
    return input_buffer;
}

/*
 * input the token now!
 * used the getline function
 * two details:
 * 1.replace the enter char with '\0' at the end
 * 2.the real length must minus 1
 */
void read_input(InputBuffer *inputBuffer) {
    ssize_t byte_read = getline(&(inputBuffer->buffer), &(inputBuffer->buffer_length), stdin);
    if (byte_read <= 0) {
        printf("Error reading input\n");
        exit(EXIT_FAILURE);
    }
    inputBuffer->input_length = byte_read - 1;
    inputBuffer->buffer[byte_read - 1] = 0;
}

/*
 * the getline function
 * lineptr :
 * a pointer to the variable we use to point to the buffer containing the read line.
 * If it set to NULL it is mallocatted by getline and should thus be freed by the user, even if the command fails.
 *
 * n :
 * a pointer to the variable we use to save the size of allocated buffer.
 *
 * stream :
 * the input stream to read from. We’ll be reading from standard input.
 *
 * return value :
 * the number of bytes read, which may be less than the size of the buffer.
 */

ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
    size_t pos;
    int c;

    if (lineptr == NULL || stream == NULL || n == NULL) {
        errno = EINVAL;
        return -1;
    }

    c = getc(stream);
    if (c == EOF) {
        return -1;
    }

    if (*lineptr == NULL) {
        *lineptr = malloc(128);
        if (*lineptr == NULL) {
            return -1;
        }
        *n = 128;
    }

    pos = 0;
    while (c != EOF) {
        if (pos + 1 >= *n) {
            size_t new_size = *n + (*n >> 2);
            if (new_size < 128) {
                new_size = 128;
            }
            char *new_ptr = realloc(*lineptr, new_size);
            if (new_ptr == NULL) {
                return -1;
            }
            *n = new_size;
            *lineptr = new_ptr;
        }

        ((unsigned char *) (*lineptr))[pos++] = c;
        if (c == '\n') {
            break;
        }
        c = getc(stream);
    }

    (*lineptr)[pos] = '\0';
    return pos;
}